package cn.redragon.soa.controller;


import cn.redragon.soa.aop.CheckReservation;
import cn.redragon.soa.common.brand.Brand;
import cn.redragon.soa.common.enums.StockActionType;
import cn.redragon.soa.common.web.ResponseDTO;
import cn.redragon.soa.model.dto.stock.ReservationDTO;
import cn.redragon.soa.service.StockService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/v1/{brand}/reservation/{type}")
@Tag(name = "Reservation API")
@Slf4j
@RequiredArgsConstructor
@Validated
public class ReservationController {

    private final StockService stockService;

    @PostMapping
    @Operation(summary = "Reserve stocks")
    @PreAuthorize("hasAuthority(#brand + ':STOCK:RW')")
    @CheckReservation(required = false)
    public ResponseDTO<Void> reserveStocks(@PathVariable Brand brand, @Parameter(name = "openid") @RequestParam String customerId,
                                           @PathVariable String type,
                                           @RequestParam String orderNumber,
                                           @RequestBody @Valid ReservationDTO reservationDTO,
                                           @RequestParam String profile) {
        reservationDTO.setCustomerId(customerId);
        reservationDTO.setOrderNumber(orderNumber);
        reservationDTO.setType(type);
        stockService.reserveStocks(brand.name(), reservationDTO, profile);
        return ResponseDTO.success();
    }

    @PutMapping
    @Operation(summary = "Return released stocks")
    @PreAuthorize("hasAuthority(#brand + ':STOCK:RW')")
    @CheckReservation(required = false, released = true)
    public ResponseDTO<Void> returnStocks(@PathVariable Brand brand, @Parameter(example = "openid") @RequestParam String customerId,
                                          @PathVariable String type,
                                          @RequestParam String orderNumber,
                                          @RequestBody @Valid ReservationDTO reservationDTO,
                                          @RequestParam String profile) {
        reservationDTO.setCustomerId(customerId);
        reservationDTO.setOrderNumber(orderNumber);
        reservationDTO.setType(type);
        stockService.returnStocks(brand.name(), reservationDTO, profile);
        return ResponseDTO.success();
    }

    @DeleteMapping(params = {"cancelType"})
    @Operation(summary = "Cancel stocks reserved")
    @PreAuthorize("hasAuthority(#brand + ':STOCK:RW')")
    @CheckReservation
    public ResponseDTO<Void> cancelReservation(@PathVariable Brand brand, @Parameter(name = "openid") @RequestParam String customerId,
                                               @PathVariable String type,
                                               @RequestParam String orderNumber,
                                               @RequestParam StockActionType cancelType,
                                               @RequestParam String profile) {
        stockService.cancelStocks(brand.name(), type, customerId, orderNumber, profile, cancelType);
        return ResponseDTO.success();
    }

    @DeleteMapping(params = {"!cancelType"})
    @Operation(summary = "Release stocks reserved")
    @PreAuthorize("hasAuthority(#brand + ':STOCK:RW')")
    @CheckReservation
    public ResponseDTO<Void> releaseReservation(@PathVariable Brand brand, @Parameter(name = "openid") @RequestParam String customerId,
                                                @PathVariable String type,
                                                @RequestParam String orderNumber,
                                                @RequestParam String profile) {
        stockService.releaseStocks(brand.name(), type, customerId, orderNumber, profile);
        return ResponseDTO.success();
    }
}
